<?php
use Workerman\Worker;
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Protocols\Http\Request;

class InteractiveClient {
    private $clientId;
    private $serverConn;
    private $peerConn;

    public function __construct($clientId, $serverHost) {
        $this->clientId = $clientId;

        // 连接中央服务器
        $this->serverConn = new AsyncTcpConnection("tcp://{$serverHost}");
        $this->serverConn->onMessage = [$this, 'handleServerMessage'];

        // 启动STUN探测
        $this->initStunDetection();
    }

    // STUN公网地址探测
    private function initStunDetection() {
        $stunConn = new AsyncUdpConnection('udp://test.51xmm.cn:3479');
        $stunConn->onMessage = function($conn, $data) {
            $publicIp = long2ip(unpack('N', substr($data, 4, 4))[1]);
            $publicPort = unpack('n', substr($data, 8, 2))[1];
            $this->registerToServer($publicIp, $publicPort);
            $conn->close();
        };
        $stunConn->connect();
    }

    // 注册到中央服务器
    private function registerToServer($publicIp, $publicPort) {
        $this->serverConn->send(json_encode([
            'type' => 'register',
            'id' => $this->clientId,
            'public_ip' => $publicIp,
            'public_port' => $publicPort
        ]));
    }

    // 处理服务端消息
    public function handleServerMessage($connection, $data) {
        $message = json_decode($data, true);

        if ($message['type'] === 'peer_info') {
            $this->connectToPeer($message['ip'], $message['port']);
        }
    }

    // 连接对端
    private function connectToPeer($ip, $port) {
        $this->peerConn = new AsyncTcpConnection("tcp://{$ip}:{$port}");
        $this->peerConn->onConnect = function($conn) {
            echo "P2P连接成功! 输入消息:\n";
            $this->startInputListener();
        };
        $this->peerConn->onMessage = function($conn, $data) {
            echo "\n[对方]: {$data}\n> ";
        };
        $this->peerConn->connect();
    }

    // 启动命令行输入监听
    private function startInputListener() {
        $stdin = new Worker('php://stdin');
        $stdin->onMessage = function($_, $data) {
            if ($this->peerConn && $this->peerConn->getStatus() === 'ESTABLISHED') {
                $this->peerConn->send(trim($data));
                echo "> ";
            } else {
                echo "连接未就绪!\n> ";
            }
        };
        Worker::runAll();
    }
}